﻿using System;
using System.Collections.Generic;
using Fetches.Fetch.Utils;

namespace Fetches.Fetch.Dto
{
    public class Request
    {
        /// <summary>
        /// 使用Segment对Request查重做调整，不同Segment对页面重爬
        /// </summary>
        public int SegmentId { get; set; }
        /// <summary>
        ///     Request可能具有亲缘性,绑定到具体的爬虫实例。Related小于0时则随机分配
        ///     实际分配需要合理算法，爬虫实例死亡是否由其他爬虫实例继承遗志需要计算
        /// </summary>
        public int RelatedTo { get; set; } = -1;
        /// <summary>
        /// 部分爬取是由Fetcher阶段确定这是索引页还是内容页的
        /// </summary>
        public bool IndexPage = false;

        private string _hash = string.Empty;

        public string Hash
        {
            get
            {
                if (string.IsNullOrEmpty(_hash))
                {
                    _hash = ComputeHash();
                }

                return _hash;
            }
        }

        /// <summary>
        ///     尝试次数,会登记到Page中这样能评估某一时段的爬取质量.
        ///     是否不再重试由order的设置和这个信息比对判断
        /// </summary>
        public int TryTimes { get; set; }

        /// <summary>
        ///     遇到反爬的重试次数
        /// </summary>
        public int AntiTryTimes { get; set; }

        public Uri Url { get; set; }

        public string Method { get; set; } = "GET";

        /// <summary>
        /// 内容
        /// </summary>
        public byte[] PostData { get; set; }
        public string PostDataType { get; set; }
        
        /// <summary>
        ///     Headers
        /// </summary>
        public Dictionary<string, string> Headers { get; set; } = new Dictionary<string, string>();

        /// <summary>
        /// User-Agent
        /// </summary>
        public string UserAgent
        {
            get => GetHeader(HttpHeaderNames.UserAgent);
            set => SetHeader(HttpHeaderNames.UserAgent, value);
        }

        /// <summary>
        /// 请求链接时Referer参数的值
        /// </summary>
        public string Referer
        {
            get => GetHeader(HttpHeaderNames.Referer);
            set => SetHeader(HttpHeaderNames.Referer, value);
        }

        /// <summary>
        /// 请求链接时Origin参数的值
        /// </summary>
        public string Origin
        {
            get => GetHeader(HttpHeaderNames.Origin);
            set => SetHeader(HttpHeaderNames.Origin, value);
        }

        /// <summary>
        /// Accept
        /// </summary>
        public string Accept
        {
            get => GetHeader(HttpHeaderNames.Accept);
            set => SetHeader(HttpHeaderNames.Accept, value);
        }

        /// <summary>
        /// 设置 Cookie
        /// </summary>
        public string Cookie
        {
            get => GetHeader(HttpHeaderNames.Cookie);
            set => SetHeader(HttpHeaderNames.Cookie, value);
        }

        public Request() { }
        public Request(string url)
        {
            this.Url = new Uri(url);
        }

        public void SetHeader(string header, string value)
        {
            if (Headers.ContainsKey(header))
            {
                Headers[header] = value.Trim();
            }
            else
            {
                Headers.Add(header, value.Trim());
            }
        }

        public string GetHeader(string header)
        {
            return Headers.ContainsKey(header) ? Headers[header] : null;
        }

        /// <summary>
        /// 不直接以Url作为查重条件,GET和POST的查重条件不一样,Post要把参数也作为查重条件
        /// </summary>
        /// <returns></returns>
        protected virtual string ComputeHash()
        {
            string requestKey;
            if (Method == "GET")
            {
                requestKey = $"{Url}{TryTimes}{SegmentId}";
            }
            else if (Method == "POST")
            {
                requestKey = $"{Url}{TryTimes}{HashHelper.Md5(PostData)}{SegmentId}";
            }
            else
            {
                requestKey = $"{Url}{TryTimes}{SegmentId}";
            }

            return HashHelper.Md5(requestKey);
        }


    }
}